package com.ceba.test.webservice.facade;

import com.ceba.test.base.enums.ErrorCode;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;

import com.ceba.base.enums.PdfOResultEnum;
import com.ceba.base.enums.SealTypeEnum;
import com.ceba.base.utils.IDSStringUtils;
import com.ceba.base.utils.PdfSignUtils;
import com.ceba.base.utils.ToPdfUtils;
import com.ceba.cebacer.KeyLoaderType;
import com.ceba.cebautils.DateUtil;
import com.ceba.base.helper.LoggerHelper;
import com.ceba.base.web.response.IResult;
import com.ceba.cebautils.IDUtils;
import com.ceba.cebautils.StringUtil;
import com.ceba.server.localKey.lm.constants.LocalLmConstants;
import com.ceba.test.base.config.LogicPathUtil;
import com.ceba.test.base.helper.SystemHelper;
import com.ceba.test.modules.admin.helper.QRCodeHelper;
import com.ceba.test.modules.filemanage.entity.GFile;
import com.ceba.test.modules.filemanage.logicService.FileManageLogicService;
import com.ceba.test.modules.storage.logicService.StorageFileCacheManage;
import com.ceba.test.webservice.entity.*;
import com.httpclient.HttpClientUtil;
import com.httpclient.common.HttpConfig;
import com.httpclient.common.HttpHeader;
import com.httpclient.exception.HttpProcessException;
import org.apache.http.Header;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ceba.service.bean.CMessage;
import com.ceba.service.bean.StatusCodeType;
import com.ceba.test.base.configs.CebaConfig;
import com.ceba.test.base.configs.CebaPathUtil;
import com.ceba.test.base.configs.CustomConfig;
import com.ceba.test.base.sign.helper.CheckSignHelper;
import com.ceba.test.base.language.ResourceUtils;
import com.ceba.test.base.web.response.WebServiceResponseInfo;
import com.ceba.test.modules.admin.entity.FTPObject;
import com.ceba.test.modules.admin.entity.GStamp;
import com.ceba.test.modules.admin.entity.ISign;
import com.ceba.test.modules.admin.helper.FTPToolHelper;
import com.ceba.test.modules.admin.logicService.AdminLogicService;
import com.ceba.test.modules.filemanage.dto.WebSignParam;
import com.ceba.test.modules.log.helper.OpLogHelper;
import com.ceba.test.modules.sign.helper.SignHelper;
import com.ceba.test.modules.sign.helper.SignInServerHelper;
import com.ceba.test.modules.statistic.entity.ReportSign;

import abc.ID;
import abc.util.FileHelper;
import configs.context.SpringBeans;

/**
 * 第三方调用--用于处理签名业务
 * 
 * @author rong
 *
 */
@SuppressWarnings("deprecation")
public class SignFacade {
	static Logger logger = LoggerFactory.getLogger(SignFacade.class);

	private final AdminLogicService adminLogicService  = SpringBeans.getAdminLogicService("adminLogicService");
	private final FileManageLogicService fileManageLogicService = SpringBeans.getFileManageLogicService("fileManageLogicService");

	public GStamp getGStamp(String stampId) throws Exception {
		GStamp gs = adminLogicService.getCorStampObjectByStampId(stampId);
		return gs;
	}
	/**
	 * 对缓存目录tempPath下的文件进行签名,并存放到目的路径
	 * 
	 * @param signId
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public WebServiceResponseInfo signFiles(String signId, Collection<File> tempDirfiles, String saveDir,
			Map<String, String> errFiles,ReportSign  parm) throws Exception {
		WebServiceResponseInfo r = new WebServiceResponseInfo();
		StringBuffer err = new StringBuffer();
		String nowTime = DateUtil.getNowTime(DateUtil.YYYYMMDDHHMMSSS);
		saveDir = StringUtil.addLastSlash(saveDir) + nowTime;
		String tempPath = "";
		String filePath = "";
		String savePath = "";
		boolean flag = false;
		String fileName = "";
		String name = "";
		String sErr = "";
		int successNum = 0;
		List<String> listSuccessPath = new ArrayList();
		List<String> qrIdList = new ArrayList<String>();
		
	   //获取isign对象
	   ISign iSign = adminLogicService.getInterfaceSignById(signId);
	   if(iSign==null){
			r.setCode(12);
			r.setMessage(ResourceUtils.getMessage("MODULES_PUBLIC_SEAL_DOES_NOT_EXIST"));
			return r;
	   } else {
	   		iSign.setStartPageOfQifeng(parm.getStartPageOfQifeng());
	   		iSign.setEndPageOfQifeng(parm.getEndPageOfQifeng());
	   }
		if (tempDirfiles != null && tempDirfiles.size() > 0) {
			Iterator it = tempDirfiles.iterator();
			while (it.hasNext()) {
				parm.setQrCodeFileId(IDUtils.getGuid());
				parm.setFileId(parm.getQrCodeFileId());

				tempPath = LogicPathUtil.getPhysicalTempDirPath(StorageFileCacheManage.getSystemUseAddressId()) + ID.getGuid() + ".pdf";
				File f = (File) it.next();
				fileName = f.getName();
				filePath = f.getPath();
				name = f.getName();
				try {
					String extName = FileHelper.getFileExtName(filePath).toLowerCase();
					if (PdfSignUtils.checkFileHasSign(filePath) && "pdf".equals(extName)) {
						err.append(ResourceUtils.getMessage("SIGNVER_FILE") + name + ResourceUtils.getMessage("MODULES_HAVE_SIGNED_NAME")+" \n ");
						errFiles.put(name, name);
						continue;
					}
					// 非pdf文件转pdf
					flag = ToPdfUtils.fileToPdf(filePath, tempPath);
					if (!flag) {
						err.append(name+ResourceUtils.getMessage(PdfOResultEnum.SIGN_ONLY_FOR_PDF.getResourceName())+" \n ");
						errFiles.put(name, name);
						continue;
					}
					if (!"pdf".equals(extName)) {
						filePath = tempPath;
					} else {
						/*if (!PdfSignUtils.checkFileHasRSASigned(filePath) && !PdfSignUtils.checkFileHasSM2Signed(filePath)) {
							String tmpPath = filePath.replace(".pdf", "-delEncrypt.pdf");
							PdfTools.deletePDFEncrypt(filePath, tmpPath);
							filePath = tmpPath;
						}*/
					}

					tempPath = LogicPathUtil.getPhysicalTempDirPath(StorageFileCacheManage.getSystemUseAddressId())+ ID.getGuid() + ".pdf";

					ISign[] iSigns = { iSign };
					FileParam fileParam = new FileParam(filePath, tempPath);
					r = insertStampAndWater2(fileParam, iSigns ,r,parm.getQrCodeFileId());
					if(r.getCode()!=0){
						return r;
					}

					tempPath = fileParam.getOutPath();
					if (!StringUtil.isEmptyString(sErr)) {
						err.append(ResourceUtils.getMessage("MODULES_SIGNATURE_FAILED") + name + ":" + sErr);
						errFiles.put(name, name);
					}
					if (!FileHelper.exists(saveDir)) {
						new File(saveDir).mkdirs();
					}
					// fileName = FileHelper.getFileName(fileName, false);
					// 如果是PDF
					if ("pdf".equals(extName)) {
						savePath = StringUtil.addLastSlash(saveDir) + fileName;
					} else {
						savePath = StringUtil.addLastSlash(saveDir) +fileName.substring(0, fileName.lastIndexOf(".")) + ".pdf";
						
					}
					
					WebServiceResponseInfo info = signPdf(tempPath, savePath,iSigns,parm);
					if (info.getCode() != 0) {
						err.append(ResourceUtils.getMessage("SIGNVER_FILE") + name + ResourceUtils.getMessage("MODULES_SIGNATURE_FAILED")+"\n ");
						if (FileHelper.exists(savePath)) {
							FileHelper.deleteFile(savePath);
						}
						errFiles.put(name, name);
						continue;
					}
					successNum++;
					listSuccessPath.add(savePath);
					if(SystemHelper.canUseQR()) {
						qrIdList.add(CebaConfig.QR_PDF_QUERY_ITF + "/" + parm.getQrCodeFileId());
					}
					//由于需要下载文档，故而需要在g_file中存储一条数据
					saveCanDownLoadFile(parm.getQrCodeFileId(),fileName,savePath);
				} catch (Exception e) {
					err.append(ResourceUtils.getMessage("SIGNVER_FILE") + name + ResourceUtils.getMessage("MODULES_FAILURE_INSET_PUBLIC_SEAL_WATERMARK")+" \n ");
					errFiles.put(name, name);
					LoggerHelper.error(logger, e, fileName + "插入公章或水印或签名时失败");
					continue;
				}
			}
			r.setMessage(err.toString());
			r.setCode(0);
			r.setSuccessNum(successNum);
			r.setSuccessPath(listSuccessPath);
			r.setErrFiles(errFiles);
			r.setQrIdList(qrIdList);
		} else {
			r.setCode(13);
			r.setMessage(ResourceUtils.getMessage("MODULES_CACHED_DIRECTORY_DOSE_NOT_NEED_SIGNATURE"));
			logger.debug(r.getMessage() + ",tempPath=" + tempPath);
			return r;
		}
		return r;
	}

	/**
	 * 判断能否签名
	 * 
	 * @return
	 */
	public WebServiceResponseInfo checkCanSign() throws Exception {
		JSONObject checkSign = CheckSignHelper.checkCanSign();
		WebServiceResponseInfo r = new WebServiceResponseInfo();
		r.setCode(Integer.valueOf(checkSign.getString("status")));
		r.setMessage(checkSign.getString("message"));
		return r;
	}

	public WebServiceResponseInfo signOfd(String filePath, String savePath, ISign[] iSigns,ReportSign parm) throws Exception {
		//加密方式 1-RSA 2-SM2
		int encodeSignType = 1;
		String srcFile = filePath;
		String dstFile = savePath;
		String stampImgPath = "";
		Integer privateKeyType = KeyLoaderType.TYPE_CEBA_KEY;
		String keyName = CebaConfig.SIGN_COMPANY;
		String algorithm = "SHA256withRSA";
		String publicKeyAlg = "RSA";

		List<IStampRule> stampRules = new ArrayList<>();

		WebServiceResponseInfo info = new WebServiceResponseInfo();
		if(iSigns !=null && iSigns.length >0){
			for( int iCount = 0 ; iCount < iSigns.length ; iCount++) {
				if (!iSigns[iCount].isNeedSinature()) {
					continue;
				}
				ISign iSig = iSigns[iCount];
				List<GStamp> gStamps =getSignStampsOfISign(iSig);

				ISign[] iSignss  = null;
				IStampRule stampRule = null;
				if(gStamps!=null && gStamps.size() >0){
					iSignss = new ISign[gStamps.size()];
					for(int i = 0 ; i < gStamps.size() ; i++){
						GStamp gs = gStamps.get(i);
						String imgPath  = LogicPathUtil.getSystemUploadPath(gs.getStorageAddressId())+ gs.getFilePath();

						stampRule = packIStampRuleFromGStamp(gs);
						stampRule.setStampImgPath(imgPath);
						if (null != iSig.getValidStartOfSeal() && !iSig.getValidStartOfSeal().isEmpty()
						    && null != iSig.getValidEndOfSeal() && !iSig.getValidEndOfSeal().isEmpty()) {
							stampRule.setValidStartOfSeal(iSig.getValidStartOfSeal());
							stampRule.setValidEndOfSeal(iSig.getValidEndOfSeal());
						}
						stampRules.add(stampRule);
						stampImgPath = imgPath;

						//将签名章信息copy给ISign对象
						iSig = GStamp.packToI_Signs(gs,iSig);
						iSig.setStampPath(imgPath);
						if(iSig.getKeyType()== KeyLoaderType.TYPE_SERVER){
							iSig.setKeyType(SystemHelper.getServerType());
							privateKeyType = SystemHelper.getServerType();
						}
						if(!StringUtil.isEmptyString(iSig.getKeyName())) {
							keyName = iSig.getKeyName();
						}
						encodeSignType = iSig.getEncodeSignType();
						iSignss[i] = iSig;
					}
				}else{
					// 透明章
					iSignss = new ISign[1];
					GStamp gStamp = new GStamp();
					String imgPath  = LogicPathUtil.getSystemUploadPath(gStamp.getStorageAddressId())+ gStamp.getFilePath();

					gStamp.setImgWidth("1");
					gStamp.setImgHeight("1");
					gStamp.setStamp_x("0");
					gStamp.setStamp_y("0");
					gStamp.setSealType(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType());
					gStamp.setStampPage("1");
					stampRule = packIStampRuleFromGStamp(gStamp);
					stampRule.setStampImgPath(imgPath);
					if (null != iSig.getValidStartOfSeal() && !iSig.getValidStartOfSeal().isEmpty()
							&& null != iSig.getValidEndOfSeal() && !iSig.getValidEndOfSeal().isEmpty()) {
						stampRule.setValidStartOfSeal(iSig.getValidStartOfSeal());
						stampRule.setValidEndOfSeal(iSig.getValidEndOfSeal());
					}
					stampRules.add(stampRule);
					stampImgPath = imgPath;

					iSig = GStamp.packToI_Signs(gStamp,iSig);
					iSig.setStampPath(imgPath);
					iSig.setImgWidth("1");
					iSig.setImgHeight("1");
					iSig.setStampX("0");
					iSig.setStampY("0");
					iSig.setSignType(Integer.valueOf(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType()));
					if(iSig.getKeyType()== KeyLoaderType.TYPE_SERVER){
						iSig.setKeyType(SystemHelper.getServerType());
						privateKeyType = SystemHelper.getServerType();
					}
					if(!StringUtil.isEmptyString(iSig.getKeyName())) {
						keyName = iSig.getKeyName();
					}
					encodeSignType = iSig.getEncodeSignType();
					iSignss[0] = iSig;
				}

				//一个规则下多个签名章对应多个签名对象
				CMessage cm = new CMessage();
				if(iSignss !=null && iSignss.length >0){
				}
			}

			if(privateKeyType != KeyLoaderType.TYPE_CEBA_KEY) {
				throw new Exception("Not support key loader type. type = " + privateKeyType);
			}
			if(encodeSignType == 2) {
				algorithm = "SM3WithSM2";
				publicKeyAlg = "EC";
			}


			ResourceBundle resourceBundle = ResourceBundle.getBundle(LocalLmConstants.LOCAL_LM_CONFIG);
			String keyPass = resourceBundle.getString(LocalLmConstants.LOCAL_LM_PASS);
			String KeyHttpUrl = resourceBundle.getString(LocalLmConstants.LOCAL_LM_HTTP_URL).replace("/alpha", "");
			PrivateKeyConf pkConf = new PrivateKeyConfLmKeyServer(KeyHttpUrl, keyPass, keyName, algorithm, publicKeyAlg);

			OfdSignContext ofdSignContext = new OfdSignContext(srcFile,dstFile,pkConf,stampRules);
			String ret = doSignOfd(ofdSignContext);
			if(null != ret && ret.isEmpty()){
				info.setCode(0);
			} else {
				info.setCode(97);
				info.setMessage(ret);
			}
		}

		return info;
	}

	private String doSignOfd(OfdSignContext ofdSignContext) {
		JSONObject ofdSignContextJson = new JSONObject(ofdSignContext);
		Header[] headers =  HttpHeader.custom()
				.userAgent("Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; Gecko)")
				.contentType("application/json")
				.build();
		HttpConfig httpConfig = HttpConfig.custom()
				.url(CebaConfig.OFD_SERVICE_URL + "/api/v1/sign/rule")
				.headers(headers)
				.encoding("utf-8")
				.json(ofdSignContextJson.toString());
		String re = null;
		logger.info("Begin sign with ofd service. url=" + httpConfig.url() + ", payload=" + httpConfig.json());
		try {
			re = HttpClientUtil.post(httpConfig);
		} catch (HttpProcessException e) {
			re = e.getMessage();
		}
		logger.info("End sign with ofd service. re=" + re);
		return re;
	}
	
	private static double pxToMM(Float val) {
		return (val / 72) * 25.4;
	}

	private static IStampRule packIStampRuleFromGStamp(GStamp gs) throws Exception {
		IStampRule iStampRule = null;
		if(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType().equalsIgnoreCase(gs.getSealType())) {
			String[] strPages = gs.getStampPage().split(",");
			List<Integer> pages = new ArrayList<>(strPages.length);
			for(String page : strPages) {
				pages.add(Integer.parseInt(page));
			}
			iStampRule = new StampRuleMultiPages(
					pages,
					pxToMM(gs.getFloatStamp_x()),
					pxToMM(gs.getFloatStamp_y()),
					pxToMM(gs.getFloatImgWidth()),
					pxToMM(gs.getFloatImgHeight()),
					gs.getFilePath(),
					true);
			return iStampRule;
		} else if (SealTypeEnum.KEYWORD_STAMP_FLAG.getType().equalsIgnoreCase(gs.getSealType())) {
			List<String> matchNames = new ArrayList<>(1);
			matchNames.add(gs.getMatchName());
			iStampRule = new StampRuleKeywords(matchNames, pxToMM(gs.getFloatImgWidth()),
					pxToMM(gs.getFloatImgHeight()),gs.getFilePath(), true);
			return  iStampRule;
		} else {
			throw new Exception("Not support stamp type. type=" +
					(gs.getSealType().equalsIgnoreCase(SealTypeEnum.KEYWORD_STAMP_FLAG.getType()) ?
							SealTypeEnum.KEYWORD_STAMP_FLAG.getValue() :
							SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getValue()));
		}
	}

	/*
	 * 签名文档--满足所有情况
	 */
	public WebServiceResponseInfo signPdf(String filePath, String savePath, ISign[] iSigns,ReportSign parm) throws Exception {
		WebServiceResponseInfo info = new WebServiceResponseInfo();
		String fileName = FileHelper.getFileName(savePath, false)+".pdf";
		if(iSigns !=null && iSigns.length >0){
			for( int iCount = 0 ; iCount < iSigns.length ; iCount++){
				if (!iSigns[iCount].isNeedSinature()) {
					continue;
				}
				ISign iSig = iSigns[iCount];
				List<GStamp> gStamps =getSignStampsOfISign(iSig);
				
				ISign[] iSignss  = null;
				if(gStamps!=null && gStamps.size() >0){
					iSignss = new ISign[gStamps.size()];
					for(int i = 0 ; i < gStamps.size() ; i++){
						GStamp gs = gStamps.get(i);
						String imgPath  = LogicPathUtil.getSystemUploadPath(gs.getStorageAddressId())+ gs.getFilePath();
						//将签名章信息copy给ISign对象
						iSig = GStamp.packToI_Signs(gs,iSig);
						iSig.setStampPath(imgPath);
						if(iSig.getKeyType()== KeyLoaderType.TYPE_SERVER){
							iSig.setKeyType(SystemHelper.getServerType());
						}
						iSignss[i] = iSig;
					}
				}else{
					iSignss = new ISign[1];
					GStamp gStamp = new GStamp();
					String imgPath  = LogicPathUtil.getSystemUploadPath(gStamp.getStorageAddressId())+ gStamp.getFilePath();
					iSig = GStamp.packToI_Signs(gStamp,iSig);
					iSig.setStampPath(imgPath);
					iSig.setImgWidth("1");
					iSig.setImgHeight("1");
					iSig.setStampX("0");
					iSig.setStampY("0");
					iSig.setSignType(Integer.valueOf(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType()));
					if(iSig.getKeyType()== KeyLoaderType.TYPE_SERVER){
						iSig.setKeyType(SystemHelper.getServerType());
					}
					iSignss[0] = iSig;
				}
				
			   String tempPath = LogicPathUtil.getPhysicalTempFolder(StorageFileCacheManage.getSystemUseAddressId())+ID.getGuid() + ".pdf";// 保存的地址
				if( iCount == iSigns.length-1){
					tempPath = savePath;
				}	
				//一个规则下多个签名章对应多个签名对象
				CMessage cm = new CMessage();
				if(iSignss !=null && iSignss.length >0){
					cm = SignInServerHelper.signPdf(filePath, tempPath, iSignss,parm);
				}
				if (StatusCodeType.CODE_200.getCode().equals(cm.getStatusCode())||
						StatusCodeType.CODE_0.getCode().equals(cm.getStatusCode())) {
					if( iCount == iSigns.length-1){
						info.setCode(Integer.valueOf(cm.getStatusCode()));
						info.setMessage(cm.getMessage());
						OpLogHelper.signOperationLogs(parm.getCreateUserIP() + "于"
								+ DateUtil.getNowTime(DateUtil.YYYY_MM_DD_HH_MM_SS) + "对报告" + fileName+ "进行签名 ");
						return info;
					}else{
						filePath = tempPath;
					}
					
				}else{
					//失败则返回
					info.setCode(Integer.valueOf(cm.getStatusCode()));
					info.setMessage(cm.getMessage()+";"+ResourceUtils.getMessage(PdfOResultEnum.PDF_EXCEPTIONS.getResourceName()));
					OpLogHelper.signOperationLogs(parm.getCreateUserIP()+ "于"
							+ DateUtil.getNowTime(DateUtil.YYYY_MM_DD_HH_MM_SS) + "对报告" + fileName + "签名签名失败");
					return info;
				}
			}
		}
		return info;
	}

	/**
	 * 获取规则对应的签名章
	 * @param iSign
	 * @return
	 * @throws Exception
	 */
	private List<GStamp> getSignStampsOfISign(ISign iSign) throws Exception {
		List<GStamp> gStamps = new ArrayList<GStamp>();
		List<String> signStampIds= IDSStringUtils.getListStringsByPrefix(iSign.getSignStampId(),",");
		if(signStampIds !=null && signStampIds.size() >0){
			for(String gsId :signStampIds){
				//获取签/章信息
				GStamp gs = adminLogicService.getStampById(gsId);
				//表示做隐形签名
				if(gs == null){
					gs = new GStamp();
					gs.setMatchName("");
					gs.setStamp_x("0");
					gs.setStamp_y("0");
					gs.setSealType(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType());
					gs.setFilePath(CebaPathUtil.getVisualtransPic());
				}
				gStamps.add(gs);
			}
		}
		
    return gStamps;
	}

	/**
	 * 插入 水印骑缝章  其他章
	 * 
	 * @return
	 */
	public WebServiceResponseInfo insertStampAndWater2(FileParam fileParam, ISign[] iSigns,
			WebServiceResponseInfo info,String qrcodeFileId) {
		IResult result = new IResult(true);
		try {
			// 取最后一个规则的水印将水印，骑缝章打入
			ISign iSign = null;
			if (iSigns.length == 1) {
				iSign = iSigns[0];
			} else {
				iSign = iSigns[iSigns.length - 1];
			}
			String filePath = fileParam.getInputPath();
			WebSignParam webSignParam = new WebSignParam();
			//控制API签名时关键字没匹配上是否报错 true-不报错 false-报错
			webSignParam.setNoErrorNotNoramlMatchKey(SystemHelper.noErrorNotNoramlMatchApiKey());
			result.set("isNoErrorNotNoramlMatchKey", webSignParam.isNoErrorNotNoramlMatchKey() ? "true":"false");
			//控制Api签名时是否添加二维码 true-允许 , 请求API时，从入参传入
			webSignParam.setAllowAddQr(SystemHelper.allowAddQrCodeKey());
			//插入水印
			if(!StringUtil.isEmptyString(iSign.getWaterStampId()) ){
				webSignParam.setWaterMarkId(iSign.getWaterStampId());
				SignHelper.insertWaterStamp(filePath, webSignParam, result);
				if(result.getResult()==true){
					fileParam.setOutPath(result.getString("filePath"));
				}else{
					fileParam.setOutPath(fileParam.getInputPath());
					info.setMessage(result.getMessage());
					info.setCode(13);
					return info;
				}
				
			}else{
				fileParam.setOutPath(fileParam.getInputPath());
			}
			
			
			
			//合并首尾页
			if(!StringUtil.isEmptyString(iSign.getMergeId()) && CebaConfig.REPORTMERGE_FLAG.equals("true")){
				webSignParam.setGFileMergeId(iSign.getMergeId());
				SignHelper.mergeFile(fileParam.getOutPath(), webSignParam, result);
				if(result.getResult()==true){
					fileParam.setOutPath(result.getString("filePath"));
				}else{
					fileParam.setOutPath(fileParam.getInputPath());
					info.setMessage(result.getMessage());
					info.setCode(31);
					return info;
				}
				
			}
			
		
			
			
			//插入骑缝章
			if(!StringUtil.isEmptyString(iSign.getQfRuleId()) && CebaConfig.QIFENG_FLAG.equals("true")){
				webSignParam.setQfStampId(iSign.getQfRuleId());
				webSignParam.setStartPageOfQifeng(iSign.getStartPageOfQifeng());
				webSignParam.setEndPageOfQifeng(iSign.getEndPageOfQifeng());
				SignHelper.insertQifeng(fileParam.getOutPath(), webSignParam, result);
				if(result.getResult()==true){
					fileParam.setOutPath(result.getString("filePath"));
				}else{
					fileParam.setOutPath(fileParam.getInputPath());
					info.setMessage(result.getMessage());
					info.setCode(31);
					return info;
				}
				
			}
			
			
			//插入其他章
			if(!StringUtil.isEmptyString(iSign.getOtherStampId())){
				String stampPath=LogicPathUtil.getPhysicalTempDirPath(StorageFileCacheManage.getSystemUseAddressId())+ID.getGuid()+".pdf";//保存的地址
				List<String> otherStampIds = IDSStringUtils.getListStringsByPrefix(iSign.getOtherStampId(),",");
				SignHelper.insertOtherSealStamps(fileParam.getOutPath(), stampPath,otherStampIds, result);
				if(result.getResult()==true){
					fileParam.setOutPath(result.getString("filePath"));
				}else{
					fileParam.setOutPath(fileParam.getInputPath());
					info.setMessage(result.getMessage());
					info.setCode(15);
					return info;
				}
			}

			// 5--是否插入二维码
			if(SystemHelper.canUseQR() && webSignParam.getAllowAddQr() == 0){
				String fileName = ID.getGuid()+".pdf";
				String stampPath=LogicPathUtil.getPhysicalTempDirPath(StorageFileCacheManage.getSystemUseAddressId())+fileName;//保存的地址
				if (qrCodekeyMatchNeedShowError(fileParam, stampPath, result, info)) {
					return info;
				}
				stampPath = QRCodeHelper.needInsertQRImage(fileParam.getOutPath(), stampPath, qrcodeFileId);
				fileParam.setOutPath(stampPath);
				result.set("filePath", stampPath);
			}

			info.setMessage(fileParam.getOutPath());
		} catch (Exception e) {
			info.setCode(16);
			info.setMessage(ResourceUtils.getMessage("MODULES_OMSERY_SEAL_WAYERMARK_INTERFACE_ANOMALY"));
			LoggerHelper.error(logger, e, "插入公章、水印时接口异常");
		}
		return info;
	}

	/**
	 * 插入 水印骑缝章  其他章
	 *
	 * @return
	 */
	public WebServiceResponseInfo insertStampAndWater3(FileParam fileParam, ISign[] iSigns,
			WebServiceResponseInfo info,String qrcodeFileId) {
		IResult result = new IResult(true);
		try {
			if (iSigns[0].isNeedSinature()) {
				// 取最后一个规则的水印将水印，骑缝章打入
				ISign iSign = null;
				if (iSigns.length == 1) {
					iSign = iSigns[0];
				} else {
					iSign = iSigns[iSigns.length - 1];
				}
				String filePath = fileParam.getInputPath();
				WebSignParam webSignParam = new WebSignParam();
				//控制API签名时关键字没匹配上是否报错 true-不报错 false-报错
				webSignParam.setNoErrorNotNoramlMatchKey(SystemHelper.noErrorNotNoramlMatchApiKey());
				result.set("isNoErrorNotNoramlMatchKey", webSignParam.isNoErrorNotNoramlMatchKey() ? "true":"false");
				//控制Api签名时是否添加二维码 true-允许
				webSignParam.setAllowAddQr(SystemHelper.allowAddQrCodeKey());
				//插入水印
				if(!StringUtil.isEmptyString(iSign.getWaterStampId()) ){
					webSignParam.setWaterMarkId(iSign.getWaterStampId());
					SignHelper.insertWaterStamp(filePath, webSignParam, result);
					if(result.getResult()==true){
						fileParam.setOutPath(result.getString("filePath"));
					}else{
						fileParam.setOutPath(fileParam.getInputPath());
						info.setMessage(result.getMessage());
						info.setCode(13);
						return info;
					}

				}else{
					fileParam.setOutPath(fileParam.getInputPath());
				}



				//合并首尾页
				if(!StringUtil.isEmptyString(iSign.getMergeId()) && CebaConfig.REPORTMERGE_FLAG.equals("true")){
					webSignParam.setGFileMergeId(iSign.getMergeId());
					SignHelper.mergeFile(fileParam.getOutPath(), webSignParam, result);
					if(result.getResult()==true){
						fileParam.setOutPath(result.getString("filePath"));
					}else{
						fileParam.setOutPath(fileParam.getInputPath());
						info.setMessage(result.getMessage());
						info.setCode(31);
						return info;
					}

				}




				//插入骑缝章
				if(!StringUtil.isEmptyString(iSign.getQfRuleId()) && CebaConfig.QIFENG_FLAG.equals("true")){
					webSignParam.setQfStampId(iSign.getQfRuleId());
					webSignParam.setStartPageOfQifeng(iSign.getStartPageOfQifeng());
					webSignParam.setEndPageOfQifeng(iSign.getEndPageOfQifeng());
					SignHelper.insertQifeng(fileParam.getOutPath(), webSignParam, result);
					if(result.getResult()==true){
						fileParam.setOutPath(result.getString("filePath"));
					}else{
						fileParam.setOutPath(fileParam.getInputPath());
						info.setMessage(result.getMessage());
						info.setCode(31);
						return info;
					}

				}


				//插入其他章
				if(!StringUtil.isEmptyString(iSign.getOtherStampId())){
					String stampPath=LogicPathUtil.getPhysicalTempDirPath(StorageFileCacheManage.getSystemUseAddressId())+ID.getGuid()+".pdf";//保存的地址
					List<String> otherStampIds = IDSStringUtils.getListStringsByPrefix(iSign.getOtherStampId(),",");
					SignHelper.insertOtherSealStampsWithCustomDate(fileParam.getOutPath(), stampPath,otherStampIds, iSign.getCustomDateToContent(), result);
					if(result.getResult()==true){
						fileParam.setOutPath(result.getString("filePath"));
					}else{
						fileParam.setOutPath(fileParam.getInputPath());
						info.setMessage(result.getMessage());
						info.setCode(15);
						return info;
					}
				}

				// 5--是否插入二维码
				if(SystemHelper.canUseQR() && webSignParam.getAllowAddQr() == 0){
					String fileName = ID.getGuid()+".pdf";
					String stampPath=LogicPathUtil.getPhysicalTempDirPath(StorageFileCacheManage.getSystemUseAddressId())+fileName;//保存的地址
					if (qrCodekeyMatchNeedShowError(fileParam, stampPath, result, info)) {
						return info;
					}
					stampPath = QRCodeHelper.needInsertQRImage(fileParam.getOutPath(), stampPath, qrcodeFileId);
					fileParam.setOutPath(stampPath);
					result.set("filePath", stampPath);
				}
			} else {
				for (int i=0; i<iSigns.length; ++i) {
					ISign iSign = iSigns[i];
					String filePath = fileParam.getInputPath();
					if (i > 0) {
						filePath = fileParam.getOutPath();
					} else {
						fileParam.setOutPath(fileParam.getInputPath());
					}
					WebSignParam webSignParam = new WebSignParam();
			    	//控制API签名时关键字没匹配上是否报错 true-不报错 false-报错
					webSignParam.setNoErrorNotNoramlMatchKey(SystemHelper.noErrorNotNoramlMatchApiKey());
					result.set("isNoErrorNotNoramlMatchKey", webSignParam.isNoErrorNotNoramlMatchKey() ? "true":"false");
					//控制Api签名时是否添加二维码 true-允许
					webSignParam.setAllowAddQr(SystemHelper.allowAddQrCodeKey());
					//插入水印
					if(!StringUtil.isEmptyString(iSign.getWaterStampId()) ){
						webSignParam.setWaterMarkId(iSign.getWaterStampId());
						SignHelper.insertWaterStamp(filePath, webSignParam, result);
						if(result.getResult()==true){
							fileParam.setOutPath(result.getString("filePath"));
						}else{
							fileParam.setOutPath(fileParam.getInputPath());
							info.setMessage(result.getMessage());
							info.setCode(13);
							return info;
						}

					}



					//合并首尾页
					if(!StringUtil.isEmptyString(iSign.getMergeId()) && CebaConfig.REPORTMERGE_FLAG.equals("true")){
						webSignParam.setGFileMergeId(iSign.getMergeId());
						SignHelper.mergeFile(fileParam.getOutPath(), webSignParam, result);
						if(result.getResult()==true){
							fileParam.setOutPath(result.getString("filePath"));
						}else{
							fileParam.setOutPath(fileParam.getInputPath());
							info.setMessage(result.getMessage());
							info.setCode(31);
							return info;
						}

					}




					//插入骑缝章
					if(!StringUtil.isEmptyString(iSign.getQfRuleId()) && CebaConfig.QIFENG_FLAG.equals("true")){
						webSignParam.setQfStampId(iSign.getQfRuleId());
						webSignParam.setStartPageOfQifeng(iSign.getStartPageOfQifeng());
						webSignParam.setEndPageOfQifeng(iSign.getEndPageOfQifeng());
						SignHelper.insertQifeng(fileParam.getOutPath(), webSignParam, result);
						if(result.getResult()==true){
							fileParam.setOutPath(result.getString("filePath"));
						}else{
							fileParam.setOutPath(fileParam.getInputPath());
							info.setMessage(result.getMessage());
							info.setCode(31);
							return info;
						}

					}


					//插入其他章
					if(!StringUtil.isEmptyString(iSign.getOtherStampId())){
						String stampPath=LogicPathUtil.getPhysicalTempDirPath(StorageFileCacheManage.getSystemUseAddressId())+ID.getGuid()+".pdf";//保存的地址
						List<String> otherStampIds = IDSStringUtils.getListStringsByPrefix(iSign.getOtherStampId(),",");
						SignHelper.insertOtherSealStampsWithCustomDate(fileParam.getOutPath(), stampPath,otherStampIds, iSign.getCustomDateToContent(), result);
						if(result.getResult()==true){
							fileParam.setOutPath(result.getString("filePath"));
						}else{
							fileParam.setOutPath(fileParam.getInputPath());
							info.setMessage(result.getMessage());
							info.setCode(15);
							return info;
						}
					}

					// 5--是否插入二维码
					if(SystemHelper.canUseQR() && webSignParam.getAllowAddQr() == 0){
						if (i == 0) {
							String fileName = ID.getGuid()+".pdf";
							String stampPath=LogicPathUtil.getPhysicalTempDirPath(StorageFileCacheManage.getSystemUseAddressId())+fileName;//保存的地址
							if (qrCodekeyMatchNeedShowError(fileParam, stampPath, result, info)) {
								return info;
							}
							stampPath = QRCodeHelper.needInsertQRImage(fileParam.getOutPath(), stampPath, qrcodeFileId);
							fileParam.setOutPath(stampPath);
							result.set("filePath", stampPath);
						}
					}
				}
			}


			info.setMessage(fileParam.getOutPath());
		} catch (Exception e) {
			info.setCode(16);
			info.setMessage(ResourceUtils.getMessage("MODULES_OMSERY_SEAL_WAYERMARK_INTERFACE_ANOMALY"));
			LoggerHelper.error(logger, e, "插入公章、水印时接口异常");
		}
		return info;
	}

	/**
	 * 给上传的文件进行加水印 、加公章、签名操作
	 * 
	 * @param ftp
	 * @param ftp
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public WebServiceResponseInfo signForUploadFile(ISign[] iSigns, String filePath, FTPObject ftp,ReportSign  parm) throws Exception {
		StringBuffer err = new StringBuffer();
		WebServiceResponseInfo info = new WebServiceResponseInfo();
		List<String> listSuccessPath = new ArrayList();
		if (!new File(filePath).exists()) {
			err.append(ResourceUtils.getMessage("MODULES_UPLOADED_DOCUMENT_DOSE_NOT_EXIST"));
			info.setMessage(err.toString());
			info.setCode(11);
			logger.debug(info.getMessage());
			return info;
		}
		String fileName = FileHelper.getFileName(filePath, false);
		String parentFileDir = filePath.replace(fileName + ".pdf", "").trim();
//		parentFileDir = StringUtil.addLastSlash(parentFileDir);
		File f = new File(filePath);
		String tempPath = LogicPathUtil.getPhysicalTempFolder(StorageFileCacheManage.getSystemUseAddressId()) + ID.getGuid() + ".pdf";
		FileParam fileParam = null;
		// 判断文档是否已经签名
		JSONObject ob = SignInServerHelper.checkFileHasSigned(filePath, iSigns);
		String savePath = parentFileDir + fileName + "_sign.pdf";
        String qrcodeFileId = parm.getQrCodeFileId();
		if (ob.getInt("code") == 12) {
			info.setMessage(ob.getString("message"));
			info.setCode(ob.getInt("code"));
			logger.debug(info.getMessage());
			return info;
		} else if (ob.getInt("code") == 1) {
			// 若文档已签名，签名服务器方式仍可继续签名
			tempPath = filePath;
		} else {
			if (!StringUtil.isEmptyString(CustomConfig.INERT_TEXT)) {
				boolean flag = ToPdfUtils.setHiddenString(filePath, tempPath, CustomConfig.INERT_TEXT);
				if (flag) {
					filePath = tempPath;
				} else {
					err.append(ResourceUtils.getMessage("MODULES_DOCUMENT_INSERTION") + CustomConfig.INERT_TEXT + ResourceUtils.getMessage("MODULES_FAIL"));
				}
			}

			tempPath = LogicPathUtil.getPhysicalTempFolder(StorageFileCacheManage.getSystemUseAddressId()) + ID.getGuid() + ".pdf";
			
			// 加水印\其他章\骑缝章
			fileParam = new FileParam(filePath, tempPath);
			info = insertStampAndWater3(fileParam, iSigns, info,qrcodeFileId);
			tempPath = fileParam.getOutPath();
			if (info.getCode() != 0) {
				return info;
			}

		}

		//仅uploadBase64FileAndSignByID和uploadFileAndSignFromFormByID支持在接口配置规则中设置“是否需要数字签名配置”
		if (isNormalSign(iSigns)) {
			//不需要数字签名
			savePath = tempPath;
			logger.info("不需要数字签名！");
		} else if (isOfdSign(iSigns)) {
			savePath = parentFileDir + fileName + "_sign.ofd";
			info = signOfd(tempPath, savePath, iSigns, parm);
		} else {
			info = signPdf(tempPath, savePath, iSigns, parm);
		}

		if (info.getCode() != 0) {
			err.append(ResourceUtils.getMessage("MODULES_PLEASE_FILE") + f.getName() + ResourceUtils.getMessage("MODULES_SIGNATURE_FAILED"));
			logger.debug(info.getMessage());
		} else {
			if (ftp != null && "true".equals(ftp.getFtpFlag())) {
				boolean flag = FTPToolHelper.upload(ftp, savePath);
				if (!flag) {
					info.setCode(22);
					info.setMessage(ResourceUtils.getMessage("MODULES_UPLOADING_DOCUMENT_ENCRYPTED") + ftp.getFtpFileName() + ResourceUtils.getMessage("MODULES_FAILURE_FTP_SERVER"));
					logger.debug(info.getMessage());
					return info;
				}
				String fName = FileHelper.getFileName(savePath, true);
				savePath = StringUtil.addLastSlash(ftp.getFtpWriteDir()) + fName;
			} else {
				int index = savePath.indexOf( CebaPathUtil.getUploadBashFilePathName());
                savePath = savePath.substring(index);
				savePath = LogicPathUtil.getBrowserPath(StorageFileCacheManage.getSystemUseAddressId(),savePath);

			}
            //相对路径
			savePath = savePath.replaceAll("\\\\", "/").replace("/WebContent", "");
			listSuccessPath.add(savePath);
			info.setMessage(err.toString());
			info.setCode(0);
			info.setSuccessNum(1);
			info.setSuccessPath(listSuccessPath);

			//由于需要下载文档，故而需要在g_file中存储一条数据
            String storageId =  StorageFileCacheManage.getSystemUseAddressId();
            savePath = LogicPathUtil.getAbsolutelyPath(storageId,savePath);
            saveCanDownLoadFile(qrcodeFileId,fileName,savePath);
		}
		return info;
	}

	private boolean isOfdSign(ISign[] iSigns) {
		for (ISign aSign : iSigns) {
			return aSign.isShouldOfd();
		}

		return false;
	}

	private boolean isNormalSign(ISign[] iSigns) {
		if (1 == iSigns.length && !iSigns[0].isNeedSinature()) {
			return true;
		}

		boolean isNormalSign = true;
		for (ISign aSign : iSigns) {
			if (aSign.isNeedSinature()) {
				isNormalSign = false;
				break;
			}
		}
		return isNormalSign;
	}

	/**
	 * 传id时获取所有的接口规则， 服务器模式CQCCA签名（可多签名）
	 * 
	 * @param iSigns
	 * @param savePath
	 * @return
	 */
	public WebServiceResponseInfo dealServerSign(ISign[] iSigns, String savePath, FTPObject ftp,ReportSign  parm) throws Exception {
		WebServiceResponseInfo info = new WebServiceResponseInfo();
		info = signForUploadFile(iSigns, savePath, ftp,parm);
		return info;
	}
	
	/**
	 * 将Isigns中的签章转换成list集合
	 * @param iSigns
	 * @return
	 * @throws Exception
	 */
	public List<GStamp> getIsignsToListStamp(ISign[] iSigns) throws Exception{
		List<GStamp> gStamps = new ArrayList<GStamp>();
		//获取最后一个签名规则
		ISign iSign = null;
		if (iSigns.length == 1) {
			iSign = iSigns[0];
		} else {
			iSign = iSigns[iSigns.length - 1];
			
		}
		List<String> signStampIds=IDSStringUtils.getListStringsByPrefix(iSign.getSignStampId(),",");
		if(signStampIds !=null && signStampIds.size() >0){
			for(String gsId :signStampIds){
				//获取签/章信息
				GStamp gs = adminLogicService.getStampById(gsId);
				//表示做隐形签名
				if(gs == null){
					gs = new GStamp();
					gs.setMatchName("");
					gs.setStamp_x("0");
					gs.setStamp_y("0");
					gs.setSealType(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType());
					gs.setFilePath(CebaPathUtil.getVisualtransPic());
				}
				gStamps.add(gs);
			}
		}
		
    return gStamps;
		
	}

    /**
     * 保存可下载的签名文件
     * @param qrcodeFileId
     * @param fileName
     * @param savePath
     */
    private void saveCanDownLoadFile(String qrcodeFileId,String fileName,String savePath) throws Exception {
        //由于需要下载文档，故而需要在g_file中存储一条数据
        GFile gFile = new GFile();
        //绝对路径
        gFile.setFilePath(savePath);
        String storageId =  StorageFileCacheManage.getSystemUseAddressId();
        //相对路径
        gFile.setVirtualPath(LogicPathUtil.getVirtualPath(storageId,savePath));
		gFile.setStorageAddressId(storageId);
        //文件后缀
        gFile.setExtName(savePath.substring(savePath.lastIndexOf(".")+1));
        //文件名称
        gFile.setFileName(fileName);
        //文档内容
        gFile.setTextContent("接口签名");
        gFile.setId(qrcodeFileId);
        // todo liguangyao 将qrCodeFileId存在数据库中
//		gFile.setQrCodeFileId(qrcodeFileId);
        fileManageLogicService.addFile(gFile);
    }

	/**
	 * 清除pdf的签名
	 * @param src
	 * @param dest
	 * @return
	 */
	public boolean deleteSignatureOfPdf(String src, String dest) {
		PdfReader reader = null;
		PdfStamper stamper = null;
		try {
			reader = new PdfReader(src);
			PdfReader.unethicalreading = true;
			stamper = new PdfStamper(reader, new FileOutputStream(dest));
			// 删除所有签名
			AcroFields fields = stamper.getAcroFields();
			List<String> names = fields.getSignatureNames();
			for (String name : names) {
				fields.removeField(name);
			}
			return true;
		} catch (Exception e) {
			return false;
		} finally {
			try {
				if (stamper != null) {
					stamper.close();
				}

				if (reader != null) {
					reader.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}
		}
	}

	/**
	 * 关键字匹配报错
	 * @param fileParam
	 * @param outPath
	 * @param result
	 * @param info
	 * @return 返回 true-报错
	 */
	private boolean qrCodekeyMatchNeedShowError(FileParam fileParam, String outPath, IResult result,
			WebServiceResponseInfo info) {
		//true-不报错 false-报错
		boolean isNoErrorNotNoramlMatchKey = result.getString("isNoErrorNotNoramlMatchKey") == "true" ? true:false;
		if (SignHelper.qrKeyMatchNeedShowError(fileParam.getOutPath(), outPath, QRCodeHelper.getQrJson(), isNoErrorNotNoramlMatchKey)) {
			fileParam.setOutPath(fileParam.getInputPath());
			info.setMessage("QrCode" + ErrorCode.CODE_33.desc);
			info.setCode(ErrorCode.CODE_33.code);
			return true;
		}
		return false;
	}
}
